﻿
using SUNRPA.CONTROLS.IMPL.domain.constant;
using SUNRPA.CONTROLS.IMPL.domain.flowItemParam;
using System;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Data;

namespace SUNRPA.CONTROLS.IMPL.domain {

    public enum TimeTriggerFrequenceEnum { 
        min,
        hour,
        day,
        month,
        week,
    }
    /// <summary>
    ///Seconds (秒)         ：可以用数字0－59 表示，
    ///Minutes(分)          ：可以用数字0－59 表示，
    ///Hours(时)            ：可以用数字0-23表示,
    ///Day-of-Month(天)  　 ：可以用数字1-31 中的任一一个值，但要注意一些特别的月份
    ///Month(月)            ：可以用0-11 或用字符串  “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
    ///Day-of-Week(每周)　　 ：可以用数字1-7表示（1 ＝ 星期日）或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
    ///
    ///“*”：指定所有的值，比如，Minutes 设置为 *，表示每分钟
    ///“/”：为特别单位，表示为“每”如“0/15”表示每隔15分钟执行一次,“0”表示为从“0”分开始, “3/20”表示表示每隔20分钟执行一次，“3”表示从第3分钟开始执行
　  ///“?”：表示每月的某一天，或第周的某一天
　  ///“L”：用于每月，或每周，表示为每月的最后一天，或每个月的最后星期几如“6L”表示“每月的最后一个星期五”
　  ///“W”：表示为最近工作日，如“15W”放在每月（day-of-month）字段上表示为“到本月15日最近的工作日”
　  ///“#”：是用来指定“的”每月第n个工作日,例 在每周（day-of-week）这个字段中内容为"6#3" or "FRI#3" 则表示“每月第三个星期五”
    /// 
    ///秒                      0-59                     , - * /  
    ///分                      0-59                     , - * /  
    ///小时                    0-23                     , - * / 
    ///日                      1-31                     , - * ? / L W C  
    ///月                      1-12 or JAN-DEC          , - * /  
    ///周几                    1-7 or SUN-SAT           , - * ? / L C #  
    ///年 (可选字段)            empty, 1970-2099        , - * /
    ///
    ///“?”字符：表示不确定的值
    ///“,”字符：指定数个值
 　 ///“-”字符：指定一个值的范围
    ///“/”字符：指定一个值的增加幅度。n/m表示从n开始，每次增加m
    ///“L”字符：用在日表示一个月中的最后一天，用在周表示该月最后一个星期X
    ///“W”字符：指定离给定日期最近的工作日(周一到周五)
    ///“#”字符：表示该月第几个周X。6#3表示该月第3个周五
    ///
    ///每隔5秒执行一次：*/5 * * * * ?
    ///每隔1分钟执行一次：0 */1 * * * ?
    ///每天23点执行一次：0 0 23 * * ?
    ///每天凌晨1点执行一次：0 0 1 * * ?
    ///每月1号凌晨1点执行一次：0 0 1 1 * ?
    ///每月最后一天23点执行一次：0 0 23 L * ?
    ///每周星期天凌晨1点实行一次：0 0 1 ? * L
    ///在26分、29分、33分执行一次：0 26,29,33 * * * ?
    ///每天的0点、13点、18点、21点都执行一次：0 0 0,13,18,21 * * ?
    ///每天的7点到21点都执行一次：0 0 7-21 * * ?
    /// </summary>
    public class TimeTriggerEntry:TriggerEntry {
        //                                    分   时    天   月   周
        public string[] exp = new string[5] { "*", "*", "*", "*", "?"};
        public TimeTriggerEntry() { 
            endDateTime = DateTime.Now;
            frequence = TimeTriggerFrequenceEnum.min;
            week1 = false;
            week2 = false;
            week3 = false;
            week4 = false;
            week5 = false;
            week6 = false;
            week7 = false;
            IsTimeEnded = false;
        }
        private TimeTriggerFrequenceEnum Frequence;
        private Int16? Minute;
        private Int16? Hour;
        private Int16? Month;
        private Boolean? Week1;
        private Boolean? Week2;
        private Boolean? Week3;
        private Boolean? Week4;
        private Boolean? Week5;
        private Boolean? Week6;
        private Boolean? Week7;
        private Boolean? IsTimeEnded;
        private DateTime? EndDateTime;

        public string GenerateExpression() { 
            int freqPos = (int)Frequence;
            StringBuilder weekExp = new StringBuilder();
            if(Week1 ?? false) { 
                weekExp.Append(",MON");
            }
            if(Week2 ?? false) { 
                weekExp.Append(",TUE");
            }
            if(Week3 ?? false) { 
                weekExp.Append(",WED");
            }
            if(Week4 ?? false) { 
                weekExp.Append(",THU");
            }
            if(Week5 ?? false) { 
                weekExp.Append(",FRI");
            }
            if(Week6 ?? false) { 
                weekExp.Append(",SAT");
            }
            if(Week7 ?? false) { 
                weekExp.Append(",SUN");
            }
            if(weekExp.Length == 0) { 
                weekExp.Append("?");
            } else { 
                weekExp.Remove(0, 1);
            }
            switch(freqPos) {
                case 0:
                    //分
                    exp[freqPos] = "*/"+minute;
                    break;
                case 1:
                    //时
                    exp[freqPos] = "*/"+hour;
                    exp[0] = minute.ToString();
                    break;
                case 2:
                    //天
                    exp[1] = hour.ToString();
                    exp[0] = minute.ToString();
                    break;
                case 3:
                    //月
                    exp[3] = month.ToString();
                    if(!weekExp.Equals("?")) {
                        exp[2] = "?";
                    }
                    exp[4] = weekExp.ToString();
                    exp[1] = hour.ToString();
                    exp[0] = minute.ToString();
                    break;
                case 4:
                    //周
                    if(!weekExp.Equals("?")) {
                        exp[2] = "?";
                    }
                    exp[freqPos] = weekExp.ToString();
                    exp[1] = hour.ToString();
                    exp[0] = minute.ToString();
                    break;
                default:
                    break;
            }
            StringBuilder sb = new StringBuilder();
            sb.Append("0");
            foreach(string subExp in exp) { 
                sb.Append(" " + subExp);
            }
            return sb.ToString();
        }
        public TimeTriggerFrequenceEnum frequence { 
            get => Frequence;
            set { 
                Frequence = value;
                NotifyPropertyChanged("frequence");
            } 
        }
        public Int16? minute { 
            get => Minute;
            set { 
                Minute = value;
                NotifyPropertyChanged("minute");
            } 
        }
        public Int16? hour { 
            get => Hour;
            set { 
                Hour = value;
                NotifyPropertyChanged("hour");
            } 
        }
        public Boolean? week1 { 
            get => Week1;
            set { 
                Week1 = value;
                NotifyPropertyChanged("week1");
            } 
        }
        public Boolean? week2 { 
            get => Week2;
            set { 
                Week2 = value;
                NotifyPropertyChanged("week2");
            } 
        }
        public Boolean? week3 { 
            get => Week3;
            set { 
                Week3 = value;
                NotifyPropertyChanged("week3");
            } 
        }
        public Boolean? week4 { 
            get => Week4;
            set { 
                Week4 = value;
                NotifyPropertyChanged("week4");
            } 
        }
        public Boolean? week5 { 
            get => Week5;
            set { 
                Week5 = value;
                NotifyPropertyChanged("week5");
            } 
        }
        public Boolean? week6 { 
            get => Week6;
            set { 
                Week6 = value;
                NotifyPropertyChanged("week6");
            } 
        }
        public Boolean? week7 { 
            get => Week7;
            set { 
                Week7 = value;
                NotifyPropertyChanged("week7");
            } 
        }
        public Int16? month { 
            get => Month;
            set { 
                Month = value;
                NotifyPropertyChanged("month");
            } 
        }               
        public Boolean? isTimeEnded { 
            get => IsTimeEnded;
            set { 
                IsTimeEnded = value;
                NotifyPropertyChanged("isTimeEnded");
            } 
        }
        public DateTime? endDateTime { 
            get => EndDateTime;
            set { 
                EndDateTime = value;
                NotifyPropertyChanged("endDateTime");
            } 
        }
    }
    public class FrequenceConverter:IValueConverter {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
            return value?.ToString() == parameter?.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
            if (bool.TryParse(value?.ToString(), out bool isChecked) && 
                Enum.TryParse<TimeTriggerFrequenceEnum>(parameter?.ToString(), out TimeTriggerFrequenceEnum param)){
                if (isChecked){
                    return param;
                }
            }
            return value;
        }
    }
}
